using System;
using NUnit.Framework;
using SmartPeople.Framework.SecuritySpace.Tests;

namespace SmartPeople.Framework.SecuritySpace.Provider.Tests
{
    [TestFixture]
    public class ISecurityPermissionProviderTests
    {
        private static readonly Guid role1ID = new Guid("{00000000-0000-0000-1001-000000000000}");
        private static readonly Guid role2ID = new Guid("{00000000-0000-0000-1002-000000000000}");
        private static readonly Guid document1ID = new Guid("{00000000-0000-0000-2001-000000000000}");


        public void Initialize(ISecuritySpace securitySpace)
        {
            //there are folders
            //ISecuritySecuredType securedFolder = securitySpace.SecuredTypes.CreateType("folder");
            ////with actions available
            //securedFolder.Actions.CreateAction(TestActions.List);
            //securedFolder.Actions.CreateAction(TestActions.Read);
            //securedFolder.Actions.CreateAction(TestActions.Create);
            //securedFolder.Actions.CreateAction(TestActions.Modify);
            //securedFolder.Actions.CreateAction(TestActions.Delete);

            //securitySpace.SecuredTypes.UpdateSecuredType(securedFolder);


            //there are unknown files
            //ISecuritySecuredType securedFile = securitySpace.SecuredTypes.CreateType("unknownFileType");
            ////with actions available
            //securedFile.Actions.CreateAction(TestActions.Read);
            //securedFile.Actions.CreateAction(TestActions.Create);
            //securedFile.Actions.CreateAction(TestActions.Modify);
            //securedFile.Actions.CreateAction(TestActions.Delete);

            //with states
            //securedFile.States.CreateState(TestStates.New);
            //securedFile.States.CreateState(TestStates.Normal);
            //securedFile.States.CreateState(TestStates.Protected);
            //securitySpace.SecuredTypes.UpdateSecuredType(securedFile);

            //there are properties
            ISecuritySecuredType baseSecuredProperty = securitySpace.SecuredTypes.CreateType("BaseProperty");
            //actions on them available
            baseSecuredProperty.Actions.CreateAction(TestActions.Get);
            baseSecuredProperty.Actions.CreateAction(TestActions.Set);
            securitySpace.SecuredTypes.UpdateSecuredType(baseSecuredProperty);
            //mod1
            ISecuritySecuredType sectype = securitySpace.SecuredTypes.GetSecuredType(BuiltInSecuredTypes.Folder);
            securitySpace.SecuredDocuments.SetDefaultPathType(sectype);
            ISecuritySecuredType secdoc = securitySpace.SecuredTypes.GetSecuredType(BuiltInSecuredTypes.UnknownFileType);
            securitySpace.SecuredDocuments.SetDefaultDocumentType(secdoc);

            //create three roles
            securitySpace.Roles.CreateRole(TestRoles.Administrators);
            securitySpace.Roles.CreateRole(TestRoles.Operators);
            securitySpace.Roles.CreateRole(TestRoles.Users);


            securitySpace.Users.CreateUser(TestUsers.System, TestUsers.User1Password, "system@acme.com",
                                           "What is you fathers middle name?", "Douglas", true, "System User Comment");
            securitySpace.Users.CreateUser(TestUsers.Administrator, "admin", "administrator@acme.com",
                                           "What is you fathers middle name?", "Douglas", true, "System User Comment");
            securitySpace.Users.CreateUser(TestUsers.Guest, "guest", "guest@acme.com",
                                           "What is you fathers middle name?", "Douglas", true, "System User Comment");
            securitySpace.Users.CreateUser(TestUsers.User1, "user1", "user1@acme.com",
                                           "What is you fathers middle name?", "Douglas", true, "System User Comment");
        }


        //SecPerm_001
        [Test, Description("Grant permission for roles on documents (tests) checking")]
        public void CreatePermissionOnRolesTests()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            ISecurityPermissions securityPermissions = TestsHelper.GetSecurityPermissions();
            bool authorized = true;
            authorized = securityPermissions.IsGranted(role1ID, document1ID);
            Assert.IsFalse(authorized);
            Assert.AreEqual(0, securityPermissions.GetPermissions(role1ID, document1ID).Length);
            //grant full control.
            securityPermissions.CreatePermission(role1ID, document1ID, AccessType.Allow);
            //check for unkown state and unkown action.
            authorized = securityPermissions.IsGranted(role1ID, document1ID);
            Assert.IsTrue(authorized, "role1 should have full control for document1");
            Assert.AreEqual(1, securityPermissions.GetPermissions(role1ID, document1ID).Length);
            //now deny all Permissions
            securityPermissions.DenyPermission(role1ID, document1ID);
            authorized = securityPermissions.IsGranted(role1ID, document1ID);
            Assert.IsFalse(authorized);
            //other roles should still not authorized  
            authorized = securityPermissions.IsGranted(role2ID, document1ID);
            Assert.IsFalse(authorized);
            //Assert.AreEqual(securedPath.FullName, securedPath1.FullName);

            securitySpace.Clear();
        }

        //SecPerm_002
        [Test, Description("Grand,Delete Permission on mulitple roles")]
        public void DeletePermissionOnRole()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            ISecurityPermissions securityPermissions = TestsHelper.GetSecurityPermissions();
            bool authorized = true;
            authorized = securityPermissions.IsGranted(role1ID, document1ID);
            Assert.IsFalse(authorized);
            Assert.AreEqual(0, securityPermissions.GetPermissions(role1ID, document1ID).Length);
            //grant full control.
            securityPermissions.CreatePermission(role1ID, document1ID, AccessType.Allow);
            //check for unkown state and unkown action.
            authorized = securityPermissions.IsGranted(role1ID, document1ID);
            Assert.IsTrue(authorized, "role1 should have full control for document1");
            Assert.AreEqual(1, securityPermissions.GetPermissions(role1ID, document1ID).Length);
            //now deny all Permissions
            securityPermissions.DenyPermission(role1ID, document1ID);
            authorized = securityPermissions.IsGranted(role1ID, document1ID);
            Assert.IsFalse(authorized);
            //other roles should still not authorized  
            authorized = securityPermissions.IsGranted(role2ID, document1ID);
            Assert.IsFalse(authorized);

            securitySpace.Clear();
        }


        //SecPerm_003
        [Test, Description("Grant control on document for a user")]
        public void GrantFullControlOnDocTypeToAUser()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            Initialize(securitySpace);
            ISecuritySecuredDocument securedDocument;
            string contactsPath = "/ACME/CRM/Contacts";
            securedDocument = securitySpace.SecuredDocuments.CreatePath(contactsPath);
            securitySpace.Roles.AddUsersToRoles(new string[] {TestUsers.User1}, new string[] {TestRoles.Operators});
            ISecurityRole roleOperators = securitySpace.Roles.GetRole(TestRoles.Operators);
            string objectPath = contactsPath + "/100";
            bool authorized;
            authorized = securitySpace.IsUserGranted(TestUsers.User1, objectPath, TestActions.Delete);
            Assert.IsFalse(authorized);
            securitySpace.SecurityPermissions.CreatePermission(roleOperators.GID, securedDocument.GID, AccessType.Allow);
            authorized = securitySpace.IsUserGranted(TestUsers.User1, objectPath, TestActions.Delete);
            Assert.IsTrue(authorized);

            securitySpace.Clear();
        }


        //SecPerm_006
        [Test, Description("Check if user has permission on path for action via token")]
        public void CheckActionControlViaUserToken()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            Initialize(securitySpace);
            ISecuritySecuredDocument securedDocument;
            string contactsPath = "/ACME/CRM/Contacts";
            securedDocument = securitySpace.SecuredDocuments.CreatePath(contactsPath);

            securitySpace.Roles.AddUsersToRoles(new string[] {TestUsers.User1}, new string[] {TestRoles.Operators});
            ISecurityRole roleOperators = securitySpace.Roles.GetRole(TestRoles.Operators);
            string objectPath = contactsPath + "/100";
            bool authorized;
            IToken user1token = securitySpace.Users.Authenticate(TestUsers.User1, "user1");
            authorized = securitySpace.IsUserGranted(user1token, objectPath, TestActions.Delete, "");
            Assert.IsFalse(authorized);
            securitySpace.SecurityPermissions.CreatePermission(roleOperators.GID, securedDocument.GID, AccessType.Allow);
            authorized = securitySpace.IsUserGranted(user1token, objectPath, TestActions.Delete, "");
            Assert.IsTrue(authorized);

            securitySpace.Clear();
        }

        //SecPerm_007
        [Test, Description("Check if user has permission on path for action")]
        public void GrantPermissionTests()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            Initialize(securitySpace);
            ISecuritySecuredDocument securedDocument;
            string contactsPath = "/ACME/CRM/Contacts";
            securedDocument = securitySpace.SecuredDocuments.CreatePath(contactsPath);
            securitySpace.Roles.AddUsersToRoles(new string[] {TestUsers.User1}, new string[] {TestRoles.Operators});
            ISecurityRole roleOperators = securitySpace.Roles.GetRole(TestRoles.Operators);
            string objectPath = contactsPath + "/100";
            bool authorized;
            authorized = securitySpace.IsUserGranted(TestUsers.User1, objectPath, TestActions.Delete);
            Assert.IsFalse(authorized);
            securitySpace.SecurityPermissions.CreatePermission(roleOperators.GID, securedDocument.GID, AccessType.Allow);
            authorized =
                securitySpace.IsUserGranted(TestUsers.User1, objectPath, TestActions.Delete, TestStates.Protected);
            Assert.IsTrue(authorized);

            securitySpace.Clear();
        }


        //SecPerm_010
        [Test, Description("Check if user has action on folder")]
        public void CheckIfUserHasRightToDeleteOnFolderWithStateViaRole()
        {
            bool authorized = true;
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            //create type folder
            ISecuritySecuredType folderType = securitySpace.SecuredTypes.CreateType("folder1");
            folderType.Actions.CreateAction(TestActions.List);
            folderType.Actions.CreateAction(TestActions.Read);
            folderType.Actions.CreateAction(TestActions.Create);
            folderType.Actions.CreateAction(TestActions.Modify);
            folderType.Actions.CreateAction(TestActions.Delete);
            folderType.States.CreateState(TestStates.New);
            securitySpace.SecuredDocuments.SetDefaultPathType(folderType);
            securitySpace.SecuredDocuments.SetDefaultDocumentType(folderType);
            ISecuritySecuredDocument securedDocument;
            string commonPath = "/ACME/TA/Common";
            securedDocument = securitySpace.SecuredDocuments.CreatePath(commonPath);
            securitySpace.SecuredTypes.UpdateSecuredType(folderType);
            //create role
            securitySpace.Roles.CreateRole(TestRoles.Users);
            //grand role permission on document path
            ISecurityPermissions securityPermissions = TestsHelper.GetSecurityPermissions();
            Guid RoleGuid = securitySpace.Roles.GetRole(TestRoles.Users).GID;
            Guid DocGuid = securitySpace.SecuredDocuments.GetDocument(commonPath).GID;
            securityPermissions.CreatePermission(RoleGuid, DocGuid, AccessType.Allow);

            //check
            authorized =
                securityPermissions.IsGranted(securitySpace.Roles.GetRole(TestRoles.Users).GID,
                                              securitySpace.SecuredDocuments.GetDocument(commonPath).GID);
            Assert.IsTrue(authorized);
            //create user
            securitySpace.Users.CreateUser("user1", "password1", "user1@acme.com", "What is you fathers middle name?",
                                           "Smith", true, "user1 comment");
            //add user to this role
            securitySpace.Roles.AddUsersToRoles(new string[] {"user1"}, new string[] {TestRoles.Users});
            //authenticate user
            IToken user1token = securitySpace.Users.Authenticate("user1", "password1");
            //check if user has permission for delete on path
            bool authorized1 = securitySpace.IsUserGranted(user1token, commonPath, TestActions.Delete, TestStates.New);
            Assert.IsTrue(authorized1);

            securitySpace.Clear();
        }


        //SecPerm_013
        [Test, Description("Test delete permission for role")]
        public void TestDeletePermission()
        {
            bool authorized = true;
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            //create type folder
            ISecuritySecuredType folderType = securitySpace.SecuredTypes.CreateType("folder2");
            folderType.Actions.CreateAction(TestActions.List);
            folderType.Actions.CreateAction(TestActions.Read);
            folderType.Actions.CreateAction(TestActions.Create);
            folderType.Actions.CreateAction(TestActions.Modify);
            folderType.Actions.CreateAction(TestActions.Delete);
            folderType.States.CreateState(TestStates.New);
            //save the above
            securitySpace.SecuredTypes.UpdateSecuredType(folderType);
            //set the default path
            securitySpace.SecuredDocuments.SetDefaultPathType(folderType);
            securitySpace.SecuredDocuments.SetDefaultDocumentType(folderType);
            ISecuritySecuredDocument securedDocument;
            string commonPath = "/ACME/TA/Common";
            securedDocument = securitySpace.SecuredDocuments.CreatePath(commonPath);
            securitySpace.SecuredTypes.UpdateSecuredType(folderType);
            //create role
            securitySpace.Roles.CreateRole(TestRoles.Users);
            ISecurityPermissionsProvider securityPermissionProvider = TestsHelper.GetSecurityPermissions();
            //get role
            Guid userRoleID = securitySpace.Roles.GetRole(TestRoles.Users).GID;
            Guid docGuid = securitySpace.SecuredDocuments.GetDocument(commonPath).GID;
            Guid actionGuid = securitySpace.SecuredDocuments.GetDocument(commonPath).GetActionID(TestActions.Create);
            Guid statGuid = securitySpace.SecuredDocuments.GetDocument(commonPath).GetStateID(TestStates.New);

            //create permission for action= create state = new allow
            securityPermissionProvider.CreatePermission(userRoleID, docGuid, actionGuid, statGuid, AccessType.Allow);
            AccessType userAccessType;
            //get access type
            userAccessType = securityPermissionProvider.GetAccessType(userRoleID, docGuid, actionGuid, statGuid);
            //confirm
            Assert.AreEqual(AccessType.Allow, userAccessType);
            //get the permission
            ISecurityPermission securityPermission =
                securityPermissionProvider.GetPermission(userRoleID, docGuid, actionGuid, statGuid);
            //delete it
            securityPermissionProvider.DeletePermission(securityPermission.GID);
            userAccessType = securityPermissionProvider.GetAccessType(userRoleID, docGuid, actionGuid, statGuid);
            //check if it has what every inherited permission
            Assert.AreEqual(AccessType.Inherited, userAccessType);

            securitySpace.Clear();
        }


        [Test, Description("Test clear permissions")]
        public void ClearPermissions()
        {
            bool authorized = true;
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            //create type folder
            ISecuritySecuredType folderType = securitySpace.SecuredTypes.CreateType("folder3");
            folderType.Actions.CreateAction(TestActions.List);
            folderType.Actions.CreateAction(TestActions.Read);
            folderType.Actions.CreateAction(TestActions.Create);
            folderType.Actions.CreateAction(TestActions.Modify);
            folderType.Actions.CreateAction(TestActions.Delete);
            folderType.States.CreateState(TestStates.New);
            //save the above
            securitySpace.SecuredTypes.UpdateSecuredType(folderType);
            //set the default path
            securitySpace.SecuredDocuments.SetDefaultPathType(folderType);
            securitySpace.SecuredDocuments.SetDefaultDocumentType(folderType);
            ISecuritySecuredDocument securedDocument;
            string commonPath = "/ACME/TA/Common";
            securedDocument = securitySpace.SecuredDocuments.CreatePath(commonPath);
            //securitySpace.SecuredTypes.UpdateSecuredType(folderType);
            //create role
            securitySpace.Roles.CreateRole(TestRoles.Users);
            ISecurityPermissionsProvider securityPermissionProvider = TestsHelper.GetSecurityPermissions();
            //get role
            Guid userRoleID = securitySpace.Roles.GetRole(TestRoles.Users).GID;
            Guid docGuid = securitySpace.SecuredDocuments.GetDocument(commonPath).GID;
            Guid actionGuid = securitySpace.SecuredDocuments.GetDocument(commonPath).GetActionID(TestActions.Create);
            Guid statGuid = securitySpace.SecuredDocuments.GetDocument(commonPath).GetStateID(TestStates.New);

            //create permission for action= create state = new allow
            securityPermissionProvider.CreatePermission(userRoleID, docGuid, actionGuid, statGuid, AccessType.Allow);
            AccessType userAccessType;
            //get access type
            userAccessType = securityPermissionProvider.GetAccessType(userRoleID, docGuid, actionGuid, statGuid);
            //confirm
            Assert.AreEqual(AccessType.Allow, userAccessType);
            //get the permission
            ISecurityPermission securityPermission =
                securityPermissionProvider.GetPermission(userRoleID, docGuid, actionGuid, statGuid);


            securitySpace.SecurityPermissions.Clear();
            //securitySpace.SecurityPermissions


            ////delete it
            //securityPermissionProvider.DeletePermission(securityPermission.GID);
            //userAccessType = securityPermissionProvider.GetAccessType(userRoleID, docGuid, actionGuid, statGuid);
            ////check if it has what every inherited permission
            //Assert.AreEqual(AccessType.Inherited, userAccessType);

            securitySpace.Clear();
        }


        [Test, Description("Testing of IsUserGranded")]
        public void IsRoleGranted()
        {
            bool authorized = true;
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            //create type folder
            ISecuritySecuredType folderType = securitySpace.SecuredTypes.CreateType("folder4");
            folderType.Actions.CreateAction(TestActions.List);
            folderType.Actions.CreateAction(TestActions.Read);
            folderType.Actions.CreateAction(TestActions.Create);
            folderType.Actions.CreateAction(TestActions.Modify);
            folderType.Actions.CreateAction(TestActions.Delete);
            folderType.States.CreateState(TestStates.New);

            securitySpace.SecuredDocuments.SetDefaultPathType(folderType);
            securitySpace.SecuredDocuments.SetDefaultDocumentType(folderType);

            ISecuritySecuredDocument securedDocument;
            string commonPath = "/ACME/TA/Common";
            securedDocument = securitySpace.SecuredDocuments.CreatePath(commonPath);
            securitySpace.SecuredTypes.UpdateSecuredType(folderType);
            //create role
            securitySpace.Roles.CreateRole(TestRoles.Users);
            //grand role permission on document path
            ISecurityPermissions securityPermissions = TestsHelper.GetSecurityPermissions();
            Guid RoleGuid = securitySpace.Roles.GetRole(TestRoles.Users).GID;
            Guid DocGuid = securitySpace.SecuredDocuments.GetDocument(commonPath).GID;
            Guid actionGuid = securitySpace.SecuredDocuments.GetDocument(commonPath).GetActionID(TestActions.Create);
            Guid statGuid = securitySpace.SecuredDocuments.GetDocument(commonPath).GetStateID(TestStates.New);
            securityPermissions.CreatePermission(RoleGuid, DocGuid, actionGuid, statGuid, AccessType.Allow);
            //securitySpace.IsRoleGranted

            securitySpace.Clear();
        }


        [Test]
        public void IsUserGrantedUserTokenAndPathTest1()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            Initialize(securitySpace);
            ISecuritySecuredDocument securedDocument;
            string contactsPath = "/ACME/CRM/Contacts";
            securedDocument = securitySpace.SecuredDocuments.CreatePath(contactsPath);

            securitySpace.Roles.AddUsersToRoles(new string[] {TestUsers.User1}, new string[] {TestRoles.Operators});
            ISecurityRole roleOperators = securitySpace.Roles.GetRole(TestRoles.Operators);
            string objectPath = contactsPath + "/100";
            bool authorized;
            IToken user1token = securitySpace.Users.Authenticate(TestUsers.User1, "user1");
//            authorized = securitySpace.IsUserGranted(user1token, objectPath, TestActions.Delete, "");
            authorized = securitySpace.IsUserGranted(user1token, objectPath);
            Assert.IsFalse(authorized);
            securitySpace.SecurityPermissions.CreatePermission(roleOperators.GID, securedDocument.GID, AccessType.Allow);
            authorized = securitySpace.IsUserGranted(user1token, objectPath);
            Assert.IsTrue(authorized);

            securitySpace.Clear();
        }

        [Test]
        public void IsUserGrantedUserTokenAndPathAndActionTest()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            Initialize(securitySpace);
            ISecuritySecuredDocument securedDocument;
            string contactsPath = "/ACME/CRM/Contacts";
            securedDocument = securitySpace.SecuredDocuments.CreatePath(contactsPath);

            securitySpace.Roles.AddUsersToRoles(new string[] { TestUsers.User1 }, new string[] { TestRoles.Operators });
            ISecurityRole roleOperators = securitySpace.Roles.GetRole(TestRoles.Operators);
            string objectPath = contactsPath + "/100";
            bool authorized;
            IToken user1token = securitySpace.Users.Authenticate(TestUsers.User1, "user1");
            //            authorized = securitySpace.IsUserGranted(user1token, objectPath, TestActions.Delete, "");
            authorized = securitySpace.IsUserGranted(user1token, objectPath, TestActions.Delete);
            Assert.IsFalse(authorized);
            securitySpace.SecurityPermissions.CreatePermission(roleOperators.GID, securedDocument.GID, AccessType.Allow);
            authorized = securitySpace.IsUserGranted(user1token, objectPath, TestActions.Delete);
            Assert.IsTrue(authorized);

            securitySpace.Clear();
        }

        [Test]
        public void IsUserGrantedUserTokenAndPathAndActionTest1()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            Initialize(securitySpace);
            ISecuritySecuredDocument securedDocument;
            string contactsPath = "/ACME/CRM/Contacts";
            securedDocument = securitySpace.SecuredDocuments.CreatePath(contactsPath);

            securitySpace.Roles.AddUsersToRoles(new string[] { TestUsers.User1 }, new string[] { TestRoles.Operators });
            ISecurityRole roleOperators = securitySpace.Roles.GetRole(TestRoles.Operators);
            string objectPath = contactsPath + "/100";
            bool authorized;
            IToken user1token = securitySpace.Users.Authenticate(TestUsers.User1, "user1");
            //            authorized = securitySpace.IsUserGranted(user1token, objectPath, TestActions.Delete, "");
            authorized = securitySpace.IsUserGranted(user1token, objectPath, TestActions.Delete,"");
            Assert.IsFalse(authorized);
            securitySpace.SecurityPermissions.CreatePermission(roleOperators.GID, securedDocument.GID, AccessType.Allow);
            authorized = securitySpace.IsUserGranted(user1token, objectPath, TestActions.Delete,"");
            Assert.IsTrue(authorized);

            securitySpace.Clear();
        }
    }
}